package com.home.jinlanhua.utils;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import org.apache.commons.codec.binary.Base64;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * 对接腾讯云存储
 * Created by lzr on 2019-08-27.
 */
public class FileUtils {

    public static void main(String[] args) {
        // 删除文件
//        String bucketName = Const.FILE_BUCKET;
//        String key = "教职工导入模板.xls";
//        getClient().deleteObject(bucketName, key);

        // 上传文件
        String result = uploadFiles("parent_model.xls");
        System.out.println(result);

        // 查询所有文件
        queryFiles("");

        // 下载文件
//        downloadFile("C:\\Users\\hades\\Desktop\\表情包杂物图\\图片上传测试1.jpg");

    }


    /**
     * 配置文件存放在同包下的Const.java中
     */

    private static COSClient cosClient;

    /**
     *
     * @return
     *      将返回一个cosclient用于操作
     */
    public static COSClient getClient() {
        if (null != cosClient) {
            return cosClient;
        }
        // 1 初始化用户身份信息（secretId, secretKey）。
        String secretId = Const.FILE_SECRET_ID;
        String secretKey = Const.FILE_SECRET_KEY;
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
        // 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
        Region region = new Region(Const.FILE_REGION);
        ClientConfig clientConfig = new ClientConfig(region);
        // 3 生成 cos 客户端。
        cosClient = new COSClient(cred, clientConfig);
        return cosClient;
    }

    /**
     * 上传文件
     * @param filePath
     *              文件路径
     * @return
     *      返回腾讯反馈的结果,可以用于日志存放
     */
    public static String uploadFiles(String filePath) {
        try {
            // 指定要上传的文件
            File localFile = new File(Const.FILE_CACHE_PATH + filePath);
            // 指定要上传到的存储桶
            String bucketName = Const.FILE_BUCKET;
            // 指定要上传到 COS 上对象键
            String key = localFile.getName();
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
            getClient().putObject(putObjectRequest);
            return filePath;
        } catch (CosClientException serverException) {
            serverException.printStackTrace();
            return null;
        }
    }

    /**
     * 查询文件
     * @param filePath
     *              文件路径
     * @return
     *      返回腾讯反馈的结果,可以用于日志存放
     */
    public static String queryFiles(String filePath) {
        try {
            String bucket = Const.FILE_BUCKET;
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
            // 设置 bucket 名称
            listObjectsRequest.setBucketName(bucket);
            // prefix 表示列出的 object 的 key 以 prefix 开始
            listObjectsRequest.setPrefix("");
            // 设置最大遍历出多少个对象, 一次 listobject 最大支持1000
            listObjectsRequest.setMaxKeys(1000);
            listObjectsRequest.setDelimiter("/");
            ObjectListing objectListing = getClient().listObjects(listObjectsRequest);
            for (COSObjectSummary cosObjectSummary : objectListing.getObjectSummaries()) {
                // 对象的路径 key
                String key = cosObjectSummary.getKey();
                // 对象的 etag
                String etag = cosObjectSummary.getETag();
                // 对象的长度
                long fileSize = cosObjectSummary.getSize();
                // 对象的存储类型
                String storageClass = cosObjectSummary.getStorageClass();
                System.out.println("key:" + key + "; etag:" + etag + "; fileSize:" + fileSize + "; storageClass:" + storageClass);
            }
            return "success";
        } catch (CosClientException serverException) {
            serverException.printStackTrace();
            return null;
        }
    }

    /**
     * 下载文件
     * @param fileKey
     *              文件名
     * @return
     *      返回腾讯反馈的结果,可以用于日志存放
     */
    public static void downloadFile(String fileKey) {
        try{
            // 指定对象所在的存储桶
            String bucketName = Const.FILE_BUCKET;

            // 指定要下载到的本地路径
            File downFile = new File(Const.FILE_CACHE_PATH + fileKey);
            if (!downFile.exists())
                downFile.createNewFile();
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, fileKey);
            getClient().getObject(getObjectRequest, downFile);
        } catch (CosClientException | IOException serverException) {
            serverException.printStackTrace();
        }
    }

    /**
     * 将一个文件落地到服务器的服务器上
     *
     * @param file
     * @return
     */
    public static String cacheFile(MultipartFile file) {
        InputStream inputStream = null;
        OutputStream os = null;
        String fileName = System.currentTimeMillis() + ".jpg";
        try {
            inputStream = file.getInputStream();
            // 2、保存到临时文件
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流保存到本地文件
            File tempFile = new File(Const.FILE_CACHE_PATH);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            os = new FileOutputStream(tempFile.getPath() + File.separator + fileName);
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 完毕，关闭所有链接
            try {
                if (os != null)
                    os.close();
                if (inputStream != null)
                    inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return fileName;
    }


    public static String makeBase64StringFromFile(MultipartFile file) {
        try {
            String fileName = FileUtils.cacheFile(file);
            File localFile = cutFile(fileName);

//            FileInputStream fis = new FileInputStream(localFile);
//            byte[] data = new byte[fis.available()];
//            fis.read(data);
//            fis.close();
            ByteArrayOutputStream outputStream = null;
            try {
                BufferedImage bufferedImage = ImageIO.read(localFile);
                outputStream = new ByteArrayOutputStream();
                ImageIO.write(bufferedImage, "jpg", outputStream);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            Base64 base64 = new Base64();
            byte[] encode = base64.encode(outputStream.toByteArray());
            return new String(encode);
        } catch ( Exception e) {
            return null;
        }
    }

    private static File cutFile(String fileName) {
        File file = new File(Const.FILE_CACHE_PATH + fileName);
        try {
            BufferedImage bufImage = ImageIO.read(file);
            int height = bufImage.getHeight();
            int width = bufImage.getWidth();
            int afterHeight;
            int afterWidth;
            if (height > width) {
                afterHeight = 500;
                afterWidth = 500 * width / height;
            } else {
                afterWidth = 500;
                afterHeight = 500 * height / width;
            }
            Image image = bufImage.getScaledInstance(afterWidth, afterHeight, Image.SCALE_SMOOTH);

            //缩放图像
            BufferedImage tag = new BufferedImage(afterWidth, afterHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = tag.createGraphics();

            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();

            OutputStream out = new FileOutputStream(Const.FILE_CACHE_PATH + fileName);
            ImageIO.write(tag, "jpg", out);// 输出
            out.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return new File(Const.FILE_CACHE_PATH + fileName);
    }
}
